package com.furtherstar.auth.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.furtherstar.auth.controller.dto.AppResourceTree;
import com.furtherstar.auth.controller.dto.AuthorizationApply;
import com.furtherstar.auth.controller.dto.AuthorizedResources;
import com.furtherstar.auth.controller.dto.PasswordChangeApply;
import com.furtherstar.auth.controller.dto.UserCredential;
import com.furtherstar.auth.dao.enums.AppResourceType;
import com.furtherstar.auth.dao.enums.Disabled;
import com.furtherstar.auth.dao.mapper.AppMapper;
import com.furtherstar.auth.dao.mapper.AppResourceMapper;
import com.furtherstar.auth.dao.mapper.AppRoleMapper;
import com.furtherstar.auth.dao.mapper.AppRoleResourceMapper;
import com.furtherstar.auth.dao.mapper.CorpDeptMapper;
import com.furtherstar.auth.dao.mapper.CorpMapper;
import com.furtherstar.auth.dao.mapper.CorpPositionMapper;
import com.furtherstar.auth.dao.mapper.CorpWorkDeptMapper;
import com.furtherstar.auth.dao.mapper.CorpWorkMapper;
import com.furtherstar.auth.dao.mapper.UserRoleMapper;
import com.furtherstar.auth.dao.model.App;
import com.furtherstar.auth.dao.model.AppExample;
import com.furtherstar.auth.dao.model.AppResource;
import com.furtherstar.auth.dao.model.AppResourceExample;
import com.furtherstar.auth.dao.model.AppRole;
import com.furtherstar.auth.dao.model.AppRoleExample;
import com.furtherstar.auth.dao.model.AppRoleResource;
import com.furtherstar.auth.dao.model.AppRoleResourceExample;
import com.furtherstar.auth.dao.model.AuthUser;
import com.furtherstar.auth.dao.model.Corp;
import com.furtherstar.auth.dao.model.CorpDept;
import com.furtherstar.auth.dao.model.CorpDeptExample;
import com.furtherstar.auth.dao.model.CorpExample;
import com.furtherstar.auth.dao.model.CorpPosition;
import com.furtherstar.auth.dao.model.CorpPositionExample;
import com.furtherstar.auth.dao.model.CorpWork;
import com.furtherstar.auth.dao.model.CorpWorkDept;
import com.furtherstar.auth.dao.model.CorpWorkDeptExample;
import com.furtherstar.auth.dao.model.CorpWorkExample;
import com.furtherstar.auth.dao.model.UserRole;
import com.furtherstar.auth.dao.model.UserRoleExample;
import com.furtherstar.auth.dao.model.UserSecret;
import com.furtherstar.auth.util.PasswordUtil;
import com.furtherstar.auth.util.SuperadminUtil;
import com.furtherstar.core.context.Work;
import com.furtherstar.core.context.WorkContext;
import com.furtherstar.core.context.WorkDept;
import com.furtherstar.core.context.WorkWithRoles;
import com.yummy.convention.collection.TreeUtils;
import com.yummy.convention.encrypt.Encrypt;
import com.yummy.convention.exception.AssertUtil;
import com.yummy.convention.spring.ApplicationContextUtil;
import com.yummy.security.User;
import com.yummy.web.config.SecurityProperties;
import com.yummy.web.config.SessionFilterProperties;
import com.yummy.web.context.RequestContext;
import com.yummy.web.context.Session;
import com.yummy.web.context.SessionManager;
import com.yummy.web.security.bean.DefaultPermission;
import com.yummy.web.security.bean.DefaultRole;
import com.yummy.web.security.bean.DefaultUser;

@Service
public class AuthService {
	
	@Autowired
	private SessionManager sessionManager;
	@Autowired
	private SecurityProperties securityProperties;
	@Autowired
	private AuthUserService authUserService;
	@Autowired
	private UserSecretService userSecretService;
	@Value("${security.secret.expiryTimeout:180}")
	private Long secretExpiryTimeout;
	@Autowired
	private UserRoleMapper userRoleMapper;
	@Autowired
	private AppMapper appMapper;
	@Autowired
	private CorpWorkMapper corpWorkMapper;
	@Autowired
	private CorpPositionMapper corpPositionMapper;
	@Autowired
	private CorpDeptMapper corpDeptMapper;
	@Autowired
	private CorpMapper corpMapper;
	@Autowired
	private CorpWorkDeptMapper corpWorkDeptMapper;
	@Autowired
	private AppResourceMapper appResourceMapper;
	@Autowired
	private AppRoleResourceMapper appRoleResourceMapper;
	@Autowired
	private AppRoleMapper appRoleMapper;
	@Autowired
	private MessageSource messageSource;

	public String login(UserCredential userCredential) {
		AuthUser authUser = findAuthUser(userCredential.getUsername());
		AssertUtil.notNull(authUser,"找不到用户");
		AssertUtil.isTrue(authUser.getDisabled() == Disabled.normal.ordinal(),"用户状态异常");
		UserSecret userSecret = findUserSecret(authUser.getId());
		AssertUtil.notNull(userSecret,"用户密码错误");
		AssertUtil.isTrue(checkPassword(userSecret,userCredential.getPassword()),"用户密码错误");
		checkMultiOnline(authUser.getUsername());
		Session session = buildSession(authUser);
		return session.getId();
	}

	private void checkMultiOnline(String username) {
		SessionFilterProperties sp = securityProperties.getSession();
		if(sp == null) {
			sp = new SessionFilterProperties();
		}
		int allowOnlineNum = sp.getAllowOnlineNum();
		allowOnlineNum = allowOnlineNum - 1;
		if(allowOnlineNum <= 0) {
			allowOnlineNum = 0;
		}
		sessionManager.remove(username,allowOnlineNum);
	}

	private Session buildSession(AuthUser authUser) {
		Session session = getOrCreateSession();
		session.setAttribute(RequestContext.CURRENT_USER, toDefaultUser(authUser));
		session.login();
		sessionManager.refresh(session);
		return session;
	}

	private User toDefaultUser(AuthUser authUser) {
		DefaultUser user = new DefaultUser();
		user.setAvatar(authUser.getAvatar());
		user.setEmail(authUser.getEmail());
		try {
			user.setMobile(authUser.getMobile() == null ? "" : Encrypt.decryptDES(authUser.getMobile(), PasswordUtil.passwordSalt));
		} catch (Exception e) {
			e.printStackTrace();
		}
		user.setNickname(authUser.getNickname());
		user.setStatus(authUser.getDisabled());
		user.setUserid(authUser.getId());
		user.setUsername(authUser.getUsername());
		return user;
	}

	private Session getOrCreateSession() {
		Session session = RequestContext.getSession();
		if(session == null) {
			session = sessionManager.create();
			RequestContext.setSession(session);
		}
		return session;
	}

	private boolean checkPassword(UserSecret userSecret, String password) {
		return PasswordUtil.checkPassword(password,userSecret);
	}

	private AuthUser findAuthUser(String username) {
		return authUserService.getByUsername(username);
	}

	private UserSecret findUserSecret(Long userid) {
		return userSecretService.getByUserid(userid);
	}

	public boolean checkUserSecretExpiry() {
		User user = RequestContext.getCurrentUser();
		UserSecret userSecret = userSecretService.getByUserid((Long)user.getUserid());
		AssertUtil.notNull(userSecret,"未知错误");
		Date lastModifyTime = userSecret.getLmTime();
		if(lastModifyTime == null) {
			return true;
		}
		Long now = System.currentTimeMillis();
		Long lastTime = lastModifyTime.getTime();
		Long expiryTimeout = secretExpiryTimeout * 24 * 3600000;
		return now - lastTime > expiryTimeout;
	}

	public void logout() {
		Session session = RequestContext.getSession();
		if(session == null) {
			return;
		}
		sessionManager.remove(session.getId());
		session.logout();
	}

	public List<App> getAuthorizedApps() {
		List<App> list = null;
		User user = RequestContext.getCurrentUser();
		if(SuperadminUtil.isSuperadmin(user)) {
			list = getAllAvaliableApps();
		}else {
			List<UserRole> userRoles = getUserRole(user);
			if(CollectionUtils.isEmpty(userRoles)) {
				return Collections.emptyList();
			}
			userRoles = filterDisabledRoles(userRoles);
			if(CollectionUtils.isEmpty(userRoles)) {
				return Collections.emptyList();
			}
			List<String> appnames = userRoles.stream().map(ur -> ur.getAppname()).distinct().toList();
			list = getAvaliableApps(appnames);
		}
		return list.stream().map(a -> {
			a.setAppTitle(messageSource.getMessage(a.getAppTitle(), null, a.getAppTitle(), ApplicationContextUtil.getLocale()));
			return a;
		}).toList();
	}

	private List<UserRole> filterDisabledRoles(List<UserRole> userRoles) {
		List<Long> roleIds = userRoles.stream().map(ur -> ur.getRoleId()).toList();
		Map<Long,AppRole> roleMap = getAvaliableRoleMap(roleIds);
		return userRoles.stream().filter(ur -> roleMap.containsKey(ur.getRoleId())).toList();
	}

	private List<App> getAllAvaliableApps() {
		AppExample example = new AppExample();
		example.createCriteria()
			.andDisabledEqualTo(Disabled.normal.ordinal());
		return appMapper.selectByExample(example);
	}

	private List<App> getAvaliableApps(List<String> appnames) {
		AppExample example = new AppExample();
		example.createCriteria().andAppnameIn(appnames)
			.andDisabledEqualTo(Disabled.normal.ordinal());
		return appMapper.selectByExample(example);
	}

	private List<UserRole> getUserRole(User user) {
		UserRoleExample example = new UserRoleExample();
		example.createCriteria().andUseridEqualTo((Long)user.getUserid());
		return userRoleMapper.selectByExample(example);
	}

	public List<CorpWork> getUserWorks() {
		User user = RequestContext.getCurrentUser();
		if(SuperadminUtil.isSuperadmin(user)) {
			return Collections.emptyList();
		}
		List<CorpWork> corpWorks = getCorpWorks(user);
		if(CollectionUtils.isEmpty(corpWorks)) {
			return Collections.emptyList();
		}
		List<Long> corpIds = corpWorks.stream().map(cw -> cw.getCorpId()).distinct().toList();
		List<Long> positionIds = corpWorks.stream().map(cw -> cw.getPositionId()).distinct().toList();
		Map<Long,CorpDept> corpMap = getAvaliableCorpMap(corpIds);
		Map<Long,CorpPosition> positionMap = getAvaliablePositionMap(positionIds);
		return corpWorks.stream().filter(cw -> corpMap.containsKey(cw.getCorpId())
				&& positionMap.containsKey(cw.getPositionId()))
				.toList();
	}

	private Map<Long, CorpPosition> getAvaliablePositionMap(List<Long> positionIds) {
		CorpPositionExample example = new CorpPositionExample();
		example.createCriteria().andIdIn(positionIds).andDisabledEqualTo(Disabled.normal.ordinal());
		List<CorpPosition> positions = corpPositionMapper.selectByExample(example);
		if(CollectionUtils.isEmpty(positions)) {
			return Collections.emptyMap();
		}
		return positions.stream().collect(Collectors.toMap(p -> p.getId(), p -> p));
	}

	private Map<Long, CorpDept> getAvaliableCorpMap(List<Long> corpIds) {
		CorpDeptExample example = new CorpDeptExample();
		example.createCriteria().andCorpIdIn(corpIds)
			.andDisabledEqualTo(Disabled.normal.ordinal());
		List<CorpDept> list = corpDeptMapper.selectByExample(example);
		if(CollectionUtils.isEmpty(list)) {
			return Collections.emptyMap();
		}
		return list.stream().collect(Collectors.toMap(d -> d.getId(), d -> d));
	}

	private List<CorpWork> getCorpWorks(User user) {
		CorpWorkExample example = new CorpWorkExample();
		example.createCriteria().andUseridEqualTo((Long)user.getUserid());
		return corpWorkMapper.selectByExample(example);
	}

	public AuthorizedResources authorize(AuthorizationApply apply) {
		User user = RequestContext.getCurrentUser();
		if(SuperadminUtil.isSuperadmin(user)) {
			List<AppResource> resources = getAllAvaliableResources(apply.getAppname());
			AuthorizedResources authorizedResources = getAuthorizedResources(resources);
			authorizedResources.getPermissions().add(superPermission());
			saveToSession(null,apply.getAppname(),Collections.emptyList(),authorizedResources.getPermissions());
			return authorizedResources;
		}
		Work work = authorizeWork(user,apply.getWorkId());
		List<AppRole> roles = getUserRoles(apply);
		List<AppResource> resources = getAvaliableResources(roles);
		AuthorizedResources authorizedResources = getAuthorizedResources(resources);
		saveToSession(work,apply.getAppname(),roles,authorizedResources.getPermissions());
		return authorizedResources;
	}

	private DefaultPermission superPermission() {
		DefaultPermission p = new DefaultPermission();
		p.setPattern("/**");
		return p;
	}

	private List<AppResource> getAllAvaliableResources(String appname) {
		AppResourceExample example = new AppResourceExample();
		example.createCriteria().andAppnameEqualTo(appname).andDisabledEqualTo(Disabled.normal.ordinal());
		return appResourceMapper.selectByExample(example);
	}

	private void saveToSession(Work work, String appname, List<AppRole> appRoles, List<DefaultPermission> permissions) {
		Session session = RequestContext.getSession();
		session.setAttribute(WorkContext.CURRENT_WORK, work);
		List<DefaultRole> roles = appRoles.stream().map(ar -> {
			DefaultRole role = new DefaultRole();
			role.setAppname(ar.getAppname());
			role.setName(ar.getName());
			role.setId(ar.getId());
			return role;
		}).toList();
		session.setAttribute(RequestContext.CURRENT_ROLES,roles);
		session.setAttribute(RequestContext.CURRENT_PERMISSIONS,permissions);
		session.setAttribute(RequestContext.CURRENT_APP, appname);
		sessionManager.refresh(session);
	}

	private AuthorizedResources getAuthorizedResources(List<AppResource> resources) {
		if(CollectionUtils.isEmpty(resources)) {
			return AuthorizedResources.empty();
		}
		List<AppResource> menus = new ArrayList<>();
		List<AppResource> apis = new ArrayList<>();
		for(AppResource r : resources) {
			if(r.getType() <= AppResourceType.page.ordinal()) {
				r.setName(messageSource.getMessage(r.getName(), null, r.getName(), ApplicationContextUtil.getLocale()));
				menus.add(r);
			}else {
				apis.add(r);
			}
		}
		List<AppResourceTree> treeMenus = toTree(menus);
		List<DefaultPermission> permissions = new ArrayList<>();
		for(AppResource a : apis){
			DefaultPermission p = new DefaultPermission();
			p.setName(a.getName());
			p.setPattern(a.getPermission());
			p.setId(a.getId());
			permissions.add(p);
		}
		List<AppResourceTree> navs = TreeUtils.toTree(treeMenus, "id", "parentId", "sort", "children", AppResourceTree.class);
		AuthorizedResources ar = new AuthorizedResources();
		ar.setNavs(navs);
		ar.setPermissions(permissions);
		return ar;
	}

	private List<AppResourceTree> toTree(List<AppResource> resources) {
		List<AppResourceTree> trees = new ArrayList<>();
		for(AppResource r : resources) {
			trees.add(toTree(r));
		}
		return trees;
	}

	private AppResourceTree toTree(AppResource r) {
		AppResourceTree t = new AppResourceTree();
		BeanUtils.copyProperties(r, t);
		return t;
	}

	private List<AppResource> getAvaliableResources(List<AppRole> roles) {
		if(CollectionUtils.isEmpty(roles)) {
			return Collections.emptyList();
		}
		List<Long> roleIds = roles.stream().map(r -> r.getId()).toList();
		List<AppRoleResource> roleResources = getRoleResources(roleIds);
		if(CollectionUtils.isEmpty(roleResources)) {
			return Collections.emptyList();
		}
		List<Long> resourceIds = roleResources.stream().map(rr -> rr.getResourceId()).toList();
		AppResourceExample example = new AppResourceExample();
		example.createCriteria().andIdIn(resourceIds).andDisabledEqualTo(Disabled.normal.ordinal());
		return appResourceMapper.selectByExample(example);
	}

	private List<AppRoleResource> getRoleResources(List<Long> roleIds) {
		AppRoleResourceExample example = new AppRoleResourceExample();
		example.createCriteria().andRoleIdIn(roleIds);
		return appRoleResourceMapper.selectByExample(example);
	}

	private List<AppRole> getUserRoles(AuthorizationApply apply) {
		List<UserRole> userRoles = getUserRoles(apply.getAppname(),apply.getWorkId());
		if(CollectionUtils.isEmpty(userRoles)) {
			return Collections.emptyList();
		}
		List<Long> roleIds = userRoles.stream().map(ur -> ur.getRoleId()).toList();
		return getAvaliableAppRoles(roleIds);
	}

	private List<AppRole> getAvaliableAppRoles(List<Long> roleIds) {
		AppRoleExample example = new AppRoleExample();
		example.createCriteria()
			.andIdIn(roleIds)
			.andDisabledEqualTo(Disabled.normal.ordinal());
		return appRoleMapper.selectByExample(example);
	}

	private List<UserRole> getUserRoles(String appname, Long workId) {
		UserRoleExample example = new UserRoleExample();
		example.createCriteria().andAppnameEqualTo(appname).andWorkIdEqualTo(workId);
		return userRoleMapper.selectByExample(example);
	}

	private Work authorizeWork(User user, Long workId) {
		CorpWork corpWork = getCorpWork(workId);
		AssertUtil.notNull(corpWork,"找不到工作");
		AssertUtil.isTrue(user.getUserid().equals(corpWork.getUserid()),"你已被记录，正在反追踪你的信息");
		List<CorpWorkDept> workDepts = getWorkDepts(corpWork.getId());
		AssertUtil.notEmpty(workDepts,"找不到工作对应的部门");
		Map<Long,CorpDept> deptMap = getAvaliableCorpDeptMap(corpWork.getCorpId());
		workDepts = workDepts.stream()
				.filter(wd -> deptMap.containsKey(wd.getDeptId()) )
				.toList();
		CorpPosition position = getPosition(corpWork.getPositionId());
		AssertUtil.notNull(position,"找不到岗位");
		return toWork(corpWork,workDepts,position,deptMap);
	}

	private Work toWork(CorpWork cw, List<CorpWorkDept> workDepts, CorpPosition position,
			Map<Long, CorpDept> deptMap) {
		Work w = new Work();
		w.setCorpId(cw.getCorpId());
		w.setCorpName(deptMap.get(cw.getCorpId()).getName());
		w.setDepts(workDepts.stream().map(wd -> {
			WorkDept d = new WorkDept();
			d.setId(wd.getDeptId());
			d.setName(deptMap.get(wd.getDeptId()).getName());
			d.setManager(wd.getManager());
			return d;
		}).toList());
		w.setManagingDeptIds(findManagingDeptIds(workDepts,deptMap));
		w.setId(cw.getId());
		w.setPositionId(cw.getPositionId());
		w.setPositionLevel(cw.getPositionLevel());
		w.setPositionType(position.getType());
		w.setPositionName(position.getName());
		w.setPrimary(cw.getPrimary() == 1 ? true : false);
		w.setUserid(cw.getUserid());
		return w;
	}

	private List<Long> findManagingDeptIds(List<CorpWorkDept> workDepts, Map<Long, CorpDept> deptMap) {
		List<Long> commonDeptIds = new ArrayList<>();
		Set<Long> managingDeptIds = new HashSet<>();
		for(CorpWorkDept wd : workDepts) {
			if(wd.getManager() == 1) {
				managingDeptIds.add(wd.getDeptId());
			}else {
				commonDeptIds.add(wd.getDeptId());
			}
		}
		Collection<CorpDept> depts = deptMap.values();
		depts.stream().forEach(d -> {
			if(managingDeptIds.contains(d.getParentId())) {
				managingDeptIds.add(d.getId());
			}
		});
		commonDeptIds.addAll(managingDeptIds);
		return commonDeptIds;
	}

	private CorpPosition getPosition(Long positionId) {
		return corpPositionMapper.selectByPrimaryKey(positionId);
	}


	private Map<Long, CorpDept> getAvaliableCorpDeptMap(Long corpId) {
		CorpDeptExample example = new CorpDeptExample();
		example.createCriteria().andCorpIdEqualTo(corpId).andDisabledEqualTo(Disabled.normal.ordinal());
		List<CorpDept> list = corpDeptMapper.selectByExample(example);
		if(CollectionUtils.isEmpty(list)) {
			return Collections.emptyMap();
		}
		return list.stream().collect(Collectors.toMap(d -> d.getId(), d -> d));
	}

	private List<CorpWorkDept> getWorkDepts(Long workId) {
		CorpWorkDeptExample example = new CorpWorkDeptExample();
		example.createCriteria().andWorkIdEqualTo(workId);
		return corpWorkDeptMapper.selectByExample(example);
	}

	private CorpWork getCorpWork(Long workId) {
		return corpWorkMapper.selectByPrimaryKey(workId);
	}

	public List<WorkWithRoles> getUserWorkWithRoles() {
		User user = RequestContext.getCurrentUser();
		if(SuperadminUtil.isSuperadmin(user)) {
			return Collections.emptyList();
		}
		List<CorpWork> corpWorks = getCorpWorks(user);
		if(CollectionUtils.isEmpty(corpWorks)) {
			return Collections.emptyList();
		}
		Long currentWorkId = WorkContext.getWork().getId();
		List<Long> positionIds = corpWorks.stream().map(cw -> cw.getPositionId()).distinct().toList();
		Map<Long,CorpPosition> positionMap = getAvaliablePositionMap(positionIds);
		List<Long> workIds = corpWorks.stream().map(cw -> cw.getId()).toList();
		List<CorpWorkDept> workDepts = getWorkDepts(workIds);
		Map<Long,Corp> corpMap = getCorpMap(workDepts.stream().map(wd -> wd.getCorpId()).distinct().toList());
		Map<Long,CorpDept> deptMap = getDeptMap(workDepts.stream().map(wd -> wd.getDeptId()).distinct().toList());
		Map<Long,List<CorpWorkDept>> workDeptMap = workDepts.stream().collect(Collectors.groupingBy(wd -> wd.getWorkId()));
		Map<Long,List<AppRole>> workRolesMap = getWorkRolesMap(workIds,RequestContext.getCurrentApp());
		return corpWorks.stream().map(cw -> {
			CorpPosition position = positionMap.get(cw.getPositionId());
			List<CorpWorkDept> currentWorkDepts = workDeptMap.get(cw.getId());
			List<AppRole> currentRoles = workRolesMap.get(cw.getId());
			Corp corp = corpMap.get(cw.getCorpId());
			if(position == null 
					|| CollectionUtils.isEmpty(currentWorkDepts) 
					|| corp == null) {
				return null;
			}
			WorkWithRoles work = toWorkWithRoles(cw,position,corp,currentWorkDepts,currentRoles,deptMap,cw.getId().equals(currentWorkId));
			return work;
		}).filter(w -> w!=null).toList();
	}

	private Map<Long, Corp> getCorpMap(List<Long> list) {
		CorpExample example = new CorpExample();
		example.createCriteria().andIdIn(list);
		List<Corp> corps = corpMapper.selectByExample(example);
		if(CollectionUtils.isEmpty(corps)) {
			return Collections.emptyMap();
		}
		return corps.stream().collect(Collectors.toMap(c -> c.getId(), c -> c));
	}

	private WorkWithRoles toWorkWithRoles(CorpWork cw, CorpPosition position, Corp corp, List<CorpWorkDept> corpWorkDepts, List<AppRole> appRoles, Map<Long, CorpDept> deptMap, boolean flag) {
		WorkWithRoles w = new WorkWithRoles();
		w.setCorpId(corp.getId());
		w.setCorpName(corp.getName());
		w.setCurrent(flag);
		w.setDepts(corpWorkDepts.stream().map(cwd -> {
			CorpDept dept = deptMap.get(cwd.getDeptId());
			if(dept == null) {
				return null;
			}
			WorkDept wd = new WorkDept();
			wd.setId(cwd.getDeptId());
			wd.setName(dept.getName());
			wd.setManager(cwd.getManager());
			return wd;
		}).filter(cwd -> cwd != null).toList());
		w.setId(cw.getId());
		w.setPositionId(position.getId());
		w.setPositionLevel(cw.getPositionLevel());
		w.setPositionName(position.getName());
		w.setPositionType(position.getType());
		w.setPrimary(cw.getPrimary() == null ? false : cw.getPrimary() == 1);
		w.setRoles(appRoles == null ? Collections.emptyList() : appRoles.stream().map(ar -> {
			DefaultRole role = new DefaultRole();
			role.setName(ar.getName());
			role.setAppname(ar.getAppname());
			return role;
		}).toList());
		return w;
	}

	private Map<Long, List<AppRole>> getWorkRolesMap(List<Long> workIds, String appname) {
		List<UserRole> userRoles = getUserRoles(appname, workIds);
		if(CollectionUtils.isEmpty(userRoles)) {
			return Collections.emptyMap();
		}
		Map<Long,AppRole> roleMap = getAvaliableRoleMap(userRoles.stream().map(ur -> ur.getRoleId()).distinct().toList());
		Map<Long,List<UserRole>> workUserRolesMap = userRoles.stream().collect(Collectors.groupingBy(ur -> ur.getWorkId()));
		Map<Long,List<AppRole>> workRolesMap = new HashMap<>();
		for(Entry<Long,List<UserRole>> entry : workUserRolesMap.entrySet()) {
			workRolesMap.put(entry.getKey(), entry.getValue().stream().map(ur -> {
				return roleMap.get(ur.getRoleId());
			}).toList());
		}
		return workRolesMap;
	}

	private Map<Long, AppRole> getAvaliableRoleMap(List<Long> roleIds) {
		List<AppRole> appRoles = getAvaliableAppRoles(roleIds);
		if(CollectionUtils.isEmpty(appRoles)) {
			return Collections.emptyMap();
		}
		return appRoles.stream().collect(Collectors.toMap(ar -> ar.getId(), ar -> ar));
	}

	private List<UserRole> getUserRoles(String appname, List<Long> workIds) {
		UserRoleExample example = new UserRoleExample();
		example.createCriteria().andAppnameEqualTo(appname).andWorkIdIn(workIds);
		return userRoleMapper.selectByExample(example);
	}

	private Map<Long, CorpDept> getDeptMap(List<Long> deptIds) {
		return getAvaliableCorpDeptMap(deptIds);
	}

	private Map<Long, CorpDept> getAvaliableCorpDeptMap(List<Long> allDeptIds) {
		CorpDeptExample example = new CorpDeptExample();
		example.createCriteria().andIdIn(allDeptIds).andDisabledEqualTo(Disabled.normal.ordinal());
		List<CorpDept> depts = corpDeptMapper.selectByExample(example);
		if(CollectionUtils.isEmpty(depts)) {
			return Collections.emptyMap();
		}
		return depts.stream().collect(Collectors.toMap(d -> d.getId(), d -> d));
	}

	private List<CorpWorkDept> getWorkDepts(List<Long> workIds) {
		CorpWorkDeptExample example = new CorpWorkDeptExample();
		example.createCriteria().andWorkIdIn(workIds);
		return corpWorkDeptMapper.selectByExample(example);
	}

	@Transactional
	public Boolean changePassword(PasswordChangeApply passwordChangeApply) {
		User user = RequestContext.getCurrentUser();
		UserSecret userSecret = findUserSecret((Long) user.getUserid());
		AssertUtil.isTrue(checkPassword(userSecret,passwordChangeApply.getOldPassword()),"密码错误");
		userSecretService.recordHistory(userSecret);
		userSecret.setPassword(PasswordUtil.encryptPassword(passwordChangeApply.getNewPassword(), user.getUserid().toString()));
		userSecretService.update(userSecret);
		return true;
	}
	
}